using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Data;
using TexasHoldEmCroupier.Views;
using TexasHoldEmCroupier.Enumerators;
using TexasHoldEmCroupier.UserControls;
using TexasHoldEmCroupier.Properties;

namespace TexasHoldEmCroupier.ApplicationController
{
    public partial class Controller
    {
        #region Members
        private MainView _MainView;
        #endregion

        #region Methods
        private void MainView_Show()
        {
            // Instantiate an instance
            this._MainView = new MainView();

            this._MainView.FormClosing += 
                new FormClosingEventHandler(MainView_FormClosing);

            // Attach the MainView to the Application Context
            this._AppContext.MainForm = this._MainView;

            // Show the form
            this._MainView.Show();

            Application.DoEvents();

            this.AddCommentaryLine(
                MessageType.Information, 
                "Welcome to Texas Hold'Em Poker");
            
            this.AddCommentaryLine(
                MessageType.Information,
                "I am your croupier");

            this.NumberOfPlayersWizardView_Show(2);

            this.StartGame();
        }

        #region Event Handlers
        private void MainView_FormClosing(
            object sender, 
            FormClosingEventArgs e)
        {
            Application.DoEvents();

            if (e.CloseReason.Equals(CloseReason.UserClosing) &&
                !this._MainView.DialogResult.Equals(DialogResult.Abort))
            {
                if (!this._MainView.NumberOfAvailablePlayers.Equals(0))
                {
                    switch (MessageBox.Show(
                       this._MainView,
                       "Are you sure you want to finish this game?",
                       this._MainView.Text,
                       MessageBoxButtons.YesNo,
                       MessageBoxIcon.Question,
                       MessageBoxDefaultButton.Button2))
                    {
                        case DialogResult.None:
                            e.Cancel = true;
                            return;
                    }
                }
            }
        }
        #endregion

        #region Private Helpers
        private void SetPlayerRoles()
        {
            if (null == this._MainView.Dealer)
            {
                this._MainView.Dealer =
                    this._MainView.GetPlayerStrip(0);
            }
            else
            {
                this._MainView.Dealer =
                    this._MainView.GetNextAvailablePlayer(
                        this._MainView.Dealer);
            }

            this.AddCommentaryLine(
                MessageType.Action,
                String.Format(
                    CultureInfo.CurrentCulture,
                    "{0} is the Dealer",
                    this._MainView.Dealer.PlayerName));

            if (this._MainView.NumberOfPlayers.Equals(2))
            {
                this._MainView.LittleBlindPlayer =
                    this._MainView.Dealer;
            }
            else
            {
                this._MainView.LittleBlindPlayer =
                    this._MainView.GetNextAvailablePlayer(
                        this._MainView.Dealer);
            }

            this.Bet(this._MainView.LittleBlindPlayer, this._MainView.SmallBlind);

            this.AddCommentaryLine(
                MessageType.Action,
                String.Format(
                    CultureInfo.CurrentCulture,
                    "{0} is the Small Blind, betting {1:N2}",
                    this._MainView.LittleBlindPlayer.PlayerName,
                    this._MainView.SmallBlind)); 
            
            this._MainView.BigBlindPlayer =
                this._MainView.GetNextAvailablePlayer(
                    this._MainView.LittleBlindPlayer);

            this.Bet(this._MainView.BigBlindPlayer, this._MainView.BigBlind);

            this.AddCommentaryLine(
                MessageType.Action,
                String.Format(
                    CultureInfo.CurrentCulture,
                    "{0} is the Big Blind, betting {1:N2}",
                    this._MainView.BigBlindPlayer.PlayerName,
                    this._MainView.BigBlind));

            this._MainView.CurrentPlayer = null;
        }

        private void ActivateNextPlayer()
        {
            if (null == this._MainView.CurrentPlayer)
            {
                this._MainView.CurrentPlayer =
                    this._MainView.BigBlindPlayer;
            }

            this._MainView.CurrentPlayer.Disable();

            if (this._MainView.NumberOfAvailablePlayers > 0)
            {
                this._MainView.CurrentPlayer =
                    this._MainView.GetNextAvailablePlayer(
                        this._MainView.CurrentPlayer);

                this._MainView.CurrentPlayer.Activate(this._MainView);

                this.AddCommentaryLine(
                    MessageType.Decision,
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "{0} to play",
                        this._MainView.CurrentPlayer.PlayerName));
            }
            else if (this._MainView.NumberOfFoldedPlayers.Equals(
                this._MainView.NumberOfPlayers - 1))
            {
                foreach (PlayerStrip thisPlayer in 
                    this._MainView.panelPlayers.Controls)
                {
                    if (thisPlayer.Action.Equals(Action.AllIn))
                    {
                        this._MainView.CurrentPlayer = thisPlayer;
                        break;
                    }
                }
                
                this._MainView.CurrentPlayer.Account +=
                    this._MainView.Pot;

                this.AddCommentaryLine(
                    MessageType.Information,
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "{0} wins the pot of {1:N2}",
                        this._MainView.CurrentPlayer.PlayerName,
                        this._MainView.Pot));

                MessageBox.Show(
                    this._MainView,
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "{0} wins the pot of {1:N2}",
                        this._MainView.CurrentPlayer.PlayerName,
                        this._MainView.Pot),
                    this._MainView.Text,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information,
                    MessageBoxDefaultButton.Button1);

                this.StartGame();
                return;
            }
            else
            {
                this.AdvanceStage();
            }
        }

        private void AdvanceStage()
        {
            switch (this._MainView.Stage)
            {
                case Stage.Flop:
                    this.AddCommentaryLine(
                        MessageType.Stop,
                        "End of betting on the Flop cards");
                    break;
                case Stage.Turn:
                    this.AddCommentaryLine(
                        MessageType.Stop,
                        "End of betting on the Turn card");
                    break;
                case Stage.River:
                    this.AddCommentaryLine(
                        MessageType.Stop,
                        "End of betting on the River card");

                    this.AssignPotView_Show();
                    return;
                case Stage.Hole:
                    this.AddCommentaryLine(
                        MessageType.Stop,
                        "End of betting on the Hole cards");
                    break;
                default:
                    break;
            }

            foreach (PlayerStrip thisPlayerStrip in
                this._MainView.panelPlayers.Controls)
            {
                thisPlayerStrip.ResetPlayerAfterStage(
                    this._MainView.Stage);
            }

            this._MainView.AdvanceStage();

            string theMessage = String.Empty;
            switch (this._MainView.Stage)
            {
                case Stage.Flop:
                    theMessage = "Deal the Flop cards";
                    break;
                case Stage.Turn:
                    theMessage = "Deal the Turn card";
                    break;
                case Stage.River:
                    theMessage = "Deal the River card";
                    break;
                default:
                    theMessage = "Deal the Hole cards";
                    break;
            }

            this.AddCommentaryLine(
                MessageType.Go,
                theMessage);

            MessageBox.Show(
                this._MainView,
                theMessage,
                this._MainView.Text,
                MessageBoxButtons.OK,
                MessageBoxIcon.Information,
                MessageBoxDefaultButton.Button1);

            this.ActivateNextPlayer();
        }

        private void StartGame()
        {
            if (this._MainView.NumberOfPlayers.Equals(1))
            {
                PlayerStrip theWinner =
                    this._MainView.panelPlayers.Controls[0]
                        as PlayerStrip;

                theWinner.IsAvailable = false;

                string theMessage =
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "{0} wins with an account of {1:N2}",
                        theWinner.PlayerName,
                        theWinner.Account);

                this.AddCommentaryLine(
                    MessageType.Information,
                    theMessage);

                MessageBox.Show(
                    this._MainView,
                    theMessage,
                    this._MainView.Text,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information,
                    MessageBoxDefaultButton.Button1);
            }
            else if (this._MainView.NumberOfPlayers > 1)
            {
                this.AddCommentaryLine(
                    MessageType.Information,
                    "Start of Game");

                foreach (PlayerStrip thisPlayerStrip in
                    this._MainView.panelPlayers.Controls)
                {
                    thisPlayerStrip.ResetPlayerAfterGame();
                }

                this._MainView.StartGame();

                this.SetPlayerRoles();

                this.AdvanceStage();
            }
        }

        private void Bet(
            PlayerStrip thePlayer,
            decimal theBetValue)
        {
            thePlayer.Account -= theBetValue;
            thePlayer.Stake += theBetValue;
            this._MainView.Pot += theBetValue;

            if (thePlayer.Stake > this._MainView.CurrentBet)
            {
                this._MainView.CurrentBet = thePlayer.Stake;
            }
        }

        private void AddCommentaryLine(
            MessageType theType,
            string theText)
        {
            switch (theType)
            {
                case MessageType.Go:
                    this._MainView.gridCommentary.Rows.Add(
                        Resources.flag_green,
                        theText);
                    break;
                case MessageType.Action:
                    this._MainView.gridCommentary.Rows.Add(
                        Resources.user_go,
                        theText);
                    break;
                case MessageType.Decision:
                    this._MainView.gridCommentary.Rows.Add(
                        Resources.comment,
                        theText);
                    break;
                case MessageType.Stop:
                    this._MainView.gridCommentary.Rows.Add(
                        Resources.stop,
                        theText);
                    break;
                default:
                    this._MainView.gridCommentary.Rows.Add(
                        Resources.information,
                        theText);
                    break;
            }

            this._MainView.gridCommentary.CurrentCell =
                this._MainView.gridCommentary.Rows[
                    this._MainView.gridCommentary.Rows.Count - 1].Cells[0];

            this._MainView.gridCommentary.ClearSelection();

            Application.DoEvents();
        }
        #endregion
        #endregion
    }
}
